home *** CD-ROM | disk | FTP | other *** search
/ Your Choice 3 / Your Choice Software Collection 3.iso / dos / secdr13d / sectsr.asm < prev    next >
Assembly Source File  |  1994-04-22  |  28KB  |  1,271 lines

  1. ; TSR disk encryptor V1.3d
  2.  
  3. DISKDATA STRUC
  4. DDDRV      DB ?       ;PHYSICAL DRIVE (HD)
  5. DRVLET      DB ?       ;DRIVE LETTER
  6. FIRSTCYL  DW ?       ;FIRST CYLINDER TO ENCRYPT
  7. FIRSTHD   DB ?       ;FIRST HEAD TO ENCRYPT
  8. FIRSTSEC  DB ?       ;FIRST SECTOR (BOOT SECTOR)
  9. LASTCYL   DW ?       ;LAST CYLINDER TO ENCRYPT
  10. MAXSEC      DB ?       ;NUMBER OF SECTORS ON DEVICE
  11. MAXHD      DB ?       ;NUMBER OF HEADS ON DEVICE
  12. SECSIZE   DW ?       ;BLOCK SIZE IN BYTES
  13. SERIAL      DW ?       ;DISK SERIAL NUMBER, FOR IV
  14.       DW ?       ;REST OF DISK SERIAL NUMBER
  15. ACTIVE      DB ?       ;CRYPT THIS DISK? FLAG
  16. FLAG2M      DB ?       ;2M-FORMATTED DISKETTE IF NZ      1.3d
  17. FATSIZ      DW ?       ;FAT SIZE FOR 2M-FORMATTED DISKETTES  1.3d
  18. DISKDATA ENDS
  19.  
  20. MAXDRV=4       ;MAX HD PARTITIONS IN SAFE MODE EWS
  21.  
  22. ;; .MODEL TINY
  23. ;; .CODE
  24. _TEXT SEGMENT PARA PUBLIC 'CODE'
  25.  ASSUME CS:_TEXT,DS:_TEXT
  26.  ORG 0100h
  27. START:
  28.  MOV AX,0800h
  29.  MOV DL,0F0h
  30.  INT 13h
  31.  MOV DX,OFFSET ALRINS
  32.  CMP AX,0EDCCh ;1.3 Already Installed?
  33.  JE  ERREX1
  34.  CMP AX,0EDCBh ;IS Previous Version ALREADY INSTALLED?
  35.  JNE LOADTSR
  36. ERREX1:
  37.  MOV AH,9
  38.  INT 21h ;PRINT ERROR AND EXIT
  39.  INT 20h
  40. LOADTSR:
  41.  MOV AH,9
  42.  MOV DX,OFFSET FKEY
  43.  INT 21h ;PRINT SIGN-ON
  44.  
  45.  MOV AX,3513h
  46.  INT 21h ;GET INT VECTOR
  47.  MOV WORD PTR[INT_JOUT+1],BX
  48.  MOV WORD PTR[INT_JOUT+3],ES
  49.  MOV WORD PTR REALBIOS,BX
  50.  MOV WORD PTR REALBIOS+2,ES
  51.  
  52.  MOV DX,OFFSET(I13_ENTRY)
  53.  MOV AX,2513h
  54.  INT 21h ;SET NEW INT VECTOR
  55.  
  56.  MOV AX,3100h
  57.  MOV DX,(END_OF_FILE-START)/16+17
  58.  INT 21h ;GO TSR
  59.  ALIGN 16
  60. TSRSTACK: ;OUR STACK GOES HERE
  61.  NOP
  62.  
  63. I13_ENTRY:
  64.  CLI
  65.  MOV WORD PTR CS:STKSEG,SS
  66.  MOV WORD PTR CS:STKOFS,SP
  67.  MOV WORD PTR CS:IV,CS
  68.  MOV SS,WORD PTR CS:IV
  69.  MOV SP,OFFSET TSRSTACK ;SETUP OUR STACK
  70.  STI
  71.  PUSH AX
  72.  PUSH BX
  73.  PUSH CX
  74.  PUSH DX
  75.  PUSH SI
  76.  PUSH DI
  77.  PUSH BP
  78.  PUSH DS
  79.  PUSH ES
  80.  PUSH CS
  81.  POP DS
  82.  
  83. ;DECIDE IF THIS REQUEST NEEDS PROCESSING
  84.  CMP AH,2 ;READ SECTOR
  85.  JE RDORWR
  86.  CMP AH,3 ;WRITE SECTOR
  87.  JE RDORWR
  88.  CMP AH,4 ;WRITE VERIFY
  89.  JE RDORWRC
  90.  CMP AH,8 ;REQUEST FOR ADDRESS?
  91.  JNE TONOPROC
  92.  CMP DL,0F0h ;CORRECT DRIVE NUMBER?
  93.  JNE TONOPROC
  94.  MOV BP,SP
  95.  MOV [BP+10],OFFSET LOADDATA ;DX=DATA ADDRESS
  96.  MOV [BP+12],CS ;CX=CODE SEGMENT
  97.  MOV AX,0EDCCh; ;THIS MEANS V 1.3+ INSTALLED (V1.2- = EDCB)
  98.  JMP RETPROG
  99.  
  100. TONOPROC:
  101.  JMP NOPROC
  102. ;
  103. ;2M13-formatted encrypted diskettes must have the buffer
  104. ;encryted before & decrypted after operation, same as real write.
  105. ;This is because 2M13 moves data from its internal buffers to user
  106. ;buffers on write verify.  I believe this is an error and have
  107. ;contacted the author of 2M13.    Until a fixed is released, this
  108. ;code intercepting write verifies is necessary.
  109. ;
  110. RDORWRC:         ;Write verify's come here 1.3d
  111.  CMP DL,1
  112.  JA  TONOPROC         ;NO Proc on hard disk
  113.  MOV BP,OFFSET FDB   ;SET DISKDATA BLOCK
  114.  JE  RDO10
  115.  MOV BP,OFFSET FDA   ;SET DISKDATA BLOCK
  116. RDO10:
  117.  CMP [BP].FLAG2M,0   ;IS THIS DISKETTE 2M-FORMATTED?
  118.  JE  TONOPROC         ;NO
  119.  CMP [BP].ACTIVE,0   ;IS THIS DISKETTE ENCRYPTED & ACTIVE?
  120.  JE  TONOPROC         ;NO
  121. RDORWR:
  122.  MOV BYTE PTR RQTYPE,AH ;STORE REQUEST TYPE
  123.  MOV BYTE PTR NUMSEC,AL ;STORE NUMBER OF SECTORS
  124.  MOV BYTE PTR STSEC,CL    ;STORE SECTOR; MUST BE MASKED
  125.  AND BYTE PTR STSEC,00111111b ;MASK OFF HIGH 2 BITS
  126.  MOV WORD PTR CALLCX,CX ;KEEP CX FOR DISK ACCESS
  127.  MOV AH,CL        ;WE NEED TO...
  128.  MOV AL,CH        ;SWAP THESE
  129.  MOV CL,6        ;ROTATE 6 BITS...
  130.  SHR AH,CL        ;TO THE RIGHT, NOW AX CONTAINS CYLINDER
  131.  MOV BYTE PTR DRIVE,DL    ;STORE DRIVE
  132.  MOV WORD PTR STCYL,AX    ;STORE CYLINDER
  133.  MOV BYTE PTR STHD,DH    ;STORE HEAD
  134.  MOV WORD PTR BUFOS,BX    ;STORE BUFFER ADDRESS
  135.  MOV WORD PTR BUFSG,ES    ;STORE BUFFER SEGMENT
  136.  
  137.  CMP DL,1           ;FLOPPY DRIVE? EWS
  138.  JBE FLOPPY
  139. ;;; CMP BYTE PTR HDNUM,DL ;IS IT ACTIVE HARD DRIVE?
  140. ;;; JNE NOTHARD
  141.  MOV BP,OFFSET HD1   ;SEARCH DISKDATA BLOCKS
  142.  MOV CX,MAXDRV
  143. SHDLP:
  144.  CMP DL,[BP].DDDRV
  145.  JNE SHDCNT
  146.  CMP AX,[BP].FIRSTCYL
  147.  JB  SHDCNT
  148.  CMP AX,[BP].LASTCYL
  149.  JA  SHDCNT
  150.  CMP [BP].ACTIVE,1    ;ACTIVE HARD DISK PARTITION?
  151.  JE  SHDFND          ;YES
  152.  MOV BYTE PTR BADKEY,1
  153.  JMP BACKFROMBIOS     ;NO. TO RETURN NOT READY
  154. SHDCNT:
  155.  ADD BP,HD2-HD1
  156.  LOOP SHDLP
  157.  JMP NOPROC          ;NOT ACTIVE & NOT SAFE. PASS THRU
  158. SHDFND:
  159.  MOV AX,OFFSET HKEY
  160.  MOV WORD PTR KEY,AX ;SET KEY
  161.  JMP PROCRQ
  162. NOTHARD:
  163. FLOPPY:
  164.  MOV AX,OFFSET FKEY
  165.  MOV WORD PTR KEY,AX ;SET FLOPPY KEY
  166.  CMP DL,0         ;IS IT DRIVE A?
  167.  JNE NOTDRIVEA
  168.  MOV BP,OFFSET FDA   ;SET DISKDATA BLOCK
  169.  JMP PROCRQ
  170. NOTDRIVEA:
  171.  CMP DL,1         ;IS IT DRIVE B?
  172.  JNE NOTDRIVEB
  173.  MOV BP,OFFSET FDB   ;SET DISKDATA BLOCK
  174.  JMP PROCRQ
  175. NOTDRIVEB:
  176. NOPROC2:
  177.  JMP NOPROC
  178.  
  179. PROCRQ: ;RIGHT DRIVE
  180.  
  181.  MOV BYTE PTR BADKEY,0 ;CLEAR BAD KEY FLAG
  182.  
  183. ;HERE WE ENCRYPT THE DATA IF IT WAS A WRITE
  184.  CMP BYTE PTR RQTYPE,4 ;WRITE VERIFY ?
  185.  JE  DOENC
  186.  CMP BYTE PTR RQTYPE,3 ;IS IT WRITE?
  187.  JNE NOENCRYPT ;IF NOT, DON'T ENCRYPT
  188. DOENC:
  189.  MOV BYTE PTR ENCRYPT,1 ;SET ENCRYPT MODE
  190.  CALL CRYPTIT ;ENCRYPT THE DATA
  191.  CMP BYTE PTR BADKEY,1
  192.  JE BACKFROMBIOS ;SKIP WRITE IF BAD KEY/NOT LOGGED IN
  193.  
  194. ;HERE WE DO THE ACTUAL DISK OPERATION
  195. NOENCRYPT:
  196.  PUSHF
  197.  PUSH CS
  198.  MOV AX,OFFSET BACKFROMBIOS
  199.  PUSH AX ;HERE WE ARE FAKING AN INT
  200.  MOV AH,BYTE PTR RQTYPE
  201.  MOV AL,BYTE PTR NUMSEC
  202.  MOV CX,WORD PTR CALLCX
  203.  MOV DH,BYTE PTR STHD
  204.  MOV DL,BYTE PTR DRIVE
  205.  MOV ES,WORD PTR BUFSG
  206.  MOV BX,WORD PTR BUFOS
  207.  JMP INT_JOUT ;GO TO BIOS
  208. BACKFROMBIOS:
  209.  PUSHF
  210.  PUSH AX
  211.  
  212. ;HERE WE DECRYPT THE DATA
  213.  MOV BYTE PTR ENCRYPT,0 ;SET DECRYPT MODE
  214.  CALL CRYPTIT ;DECRYPT THE DATA
  215.  
  216. ;HERE WE RETURN TO THE CALLING PROGRAM
  217.  POP AX ;INT RETURN CODE
  218.  POP BX ;FLAGS
  219.  
  220.  CMP BYTE PTR BADKEY,1 ;RETURN FAKE ERROR?
  221.  JNE NOERRRET
  222.  OR BL,1      ;SET CARRY IF KEY BAD
  223.  MOV AH,80h   ;SIMULATE NO DISK PRESENT ERROR
  224.  
  225. NOERRRET:
  226.  MOV ES,WORD PTR STKSEG
  227.  MOV SI,WORD PTR STKOFS
  228.  MOV ES:[SI+4],BX ;PUT NEW FLAGS WHERE IRET WILL RECALL THEM
  229.  
  230. RETPROG:
  231.  POP ES
  232.  POP DS
  233.  POP BP
  234.  POP DI
  235.  POP SI
  236.  POP DX
  237.  POP CX
  238.  POP BX
  239.  CLI
  240.  MOV SS,WORD PTR CS:STKSEG
  241.  MOV SP,WORD PTR CS:STKOFS ;RESTORE USER STACK
  242.  STI
  243.  IRET ;RETURN TO PROGRAM, LOADING MODIFIED FLAGS
  244.  
  245. NOPROC: ;REQUESTS NOT PROCESSED JUMP HERE
  246.  POP ES
  247.  POP DS
  248.  POP BP
  249.  POP DI
  250.  POP SI
  251.  POP DX
  252.  POP CX
  253.  POP BX
  254.  POP AX
  255.  CLI
  256.  MOV SS,WORD PTR CS:STKSEG
  257.  MOV SP,WORD PTR CS:STKOFS ;RESTORE USER STACK
  258.  STI
  259.  
  260. INT_JOUT:
  261.  DB 0EAh,00,00,00,00 ;JMP FAR
  262.  
  263. CRYPTIT: ;THIS ENCRYPTS OR DECRYPTS THE BUFFER
  264.  MOV AL,BYTE PTR NUMSEC
  265.  MOV BYTE PTR SECLFT,AL ;LOAD SECTOR COUNTER
  266.  MOV AX,WORD PTR STCYL
  267.  MOV WORD PTR CURCYL,AX ;LOAD CURRENT CYLINDER
  268.  MOV AL,BYTE PTR STHD
  269.  MOV BYTE PTR CURHD,AL    ;LOAD CURRENT HEAD
  270.  MOV AL,BYTE PTR STSEC
  271.  MOV BYTE PTR CURSEC,AL ;LOAD CURRENT SECTOR
  272.  MOV AX,WORD PTR BUFOS
  273.  MOV WORD PTR BUFPS,AX    ;LOAD BUFFER POINTER
  274.  
  275. CRYPTLOOP:
  276.  CMP BYTE PTR SECLFT,0
  277.  JE DONECRYPT ;CHECK FOR LAST SECTOR
  278.  
  279.  MOV AX,WORD PTR CURCYL
  280.  CMP AX,[BP].FIRSTCYL
  281.  JB DONTCRYPTSEC
  282.  JNE NOTBOOTSEC
  283.  
  284.  MOV AL,BYTE PTR CURHD
  285.  CMP AL,[BP].FIRSTHD
  286.  JB DONTCRYPTSEC
  287.  JNE NOTBOOTSEC
  288.  
  289.  MOV AL,BYTE PTR CURSEC
  290.  CMP AL,[BP].FIRSTSEC
  291. ;DO WE NEED A JB HERE?
  292.  JNE NOTBOOTSEC
  293.  
  294.  CALL LOADBS ;LOAD DATA FROM BOOT SECTOR
  295.  JMP DONTCRYPTSEC
  296.  
  297. NOTBOOTSEC:
  298.  MOV AX,WORD PTR CURCYL
  299.  CMP AX,[BP].LASTCYL
  300.  JA DONTCRYPTSEC
  301.  
  302.  CMP [BP].ACTIVE,1
  303.  JE DOCRYPTSEC      ;CHECK ACTIVE FLAG
  304.  CMP BYTE PTR DRIVE,1
  305.  JBE DONTCRYPTSEC
  306.  MOV BYTE PTR BADKEY,1
  307.  JMP DONTCRYPTSEC
  308. DOCRYPTSEC:
  309.  CALL CRYPTSEC ;ENCRYPT CURRENT SECTOR
  310. DONTCRYPTSEC:
  311.  CALL NEXTSEC  ;GO ON TO NEXT SECTOR
  312.  JMP CRYPTLOOP       ;LOOP
  313. DONECRYPT: RET
  314.  
  315. CRYPTSEC: ;HERE WE CRYPT ONE SECTOR
  316. ;SET UP IV
  317. ;For 2M-formatted diskettes, IV must be the same for FAT1 and FAT2
  318. ;because 2M omits FAT2 and remaps read requests to FAT1  1.3d
  319.  CMP [BP].FLAG2M,0     ;Must be 2M-formatted diskette
  320.  JE  NOT_FAT2
  321.  MOV AX,WORD PTR CURCYL
  322.  CMP AX,2
  323.  JA  NOT_FAT2
  324.  SHL AL,1         ;ALWAYS 2 HD/CYL FOR DISKETTES
  325.  PUSH CX
  326.  MOV CL,BYTE PTR CURHD
  327.  MOV CH,0
  328.  ADD AX,CX
  329.  MUL   [BP].MAXSEC
  330.  MOV CL,BYTE PTR CURSEC
  331.  MOV CH,0
  332.  ADD   AX,CX         ; sector
  333.  DEC   AX         ; AX = Relative DOS Sector
  334.  MOV CX,[BP].FATSIZ
  335.  CMP AX,CX
  336.  JNA NOT_FAT2P           ;Below FAT 2
  337.  SHL CX,1
  338.  CMP AX,CX
  339.  JA  NOT_FAT2P           ;Above FAT 2
  340.  SUB AX,[BP].FATSIZ    ;in FAT 2 of 2M diskette. Dup FAT1 IV
  341.  DIV   [BP].MAXSEC
  342.  INC   AH         ; Numbered from 1...
  343.  MOV   BYTE PTR IV+3,AH  ; ...the Remainder is the sector
  344.  SHR   AL,1
  345.  MOV   AH,0
  346.  MOV   WORD PTR IV,AX     ; Cylinder
  347.  RCL   AL,1
  348.  AND   AL,1
  349.  MOV   BYTE PTR IV+2,AL  ; Head
  350.  POP   CX
  351.  JMP FATCOM
  352. NOT_FAT2P:
  353.  POP CX
  354. NOT_FAT2:
  355.  MOV AX,WORD PTR CURCYL
  356.  MOV WORD PTR IV,AX
  357.  MOV AL,BYTE PTR CURHD
  358.  MOV BYTE PTR IV+2,AL
  359.  MOV AL,BYTE PTR CURSEC
  360.  MOV BYTE PTR IV+3,AL
  361. FATCOM:
  362.  MOV AX,[BP].SERIAL
  363.  MOV WORD PTR IV+4,AX
  364.  MOV AX,[BP].SERIAL+2
  365.  MOV WORD PTR IV+6,AX ;SET UP IV
  366.  
  367. ;PRE-ENCRYPT IV
  368.  MOV AX,1  ;ACTUALLY ZERO BLOCKS, WILL JUST PRE-ENCRYPT IV
  369.  PUSH AX   ;STORE NUMBER OF BLOCKS
  370.  SUB SP,8 ;PRETEND TO PUSH PLAINTEXT/CIPHERTEXT ADDRESSES
  371.  MOV AX,WORD PTR KEY
  372.  PUSH CS
  373.  PUSH AX
  374.  MOV AX,OFFSET IV
  375.  PUSH CS
  376.  PUSH AX
  377.  PUSH AX ;MAKE IT LOOK LIKE A FAR CALL FOR IDEACFB
  378.  CALL _IDEACFB
  379.  ADD SP,20 ;REMOVE EXTRA WORD
  380.  
  381. ;ENCRYPT/DECRYPT THE BLOCK
  382.  MOV AX,[BP].SECSIZE
  383.  MOV CL,3
  384.  SHR AX,CL ;SECSIZE/8
  385.  INC AX    ;ONE BLOCK (IV) NOT USED
  386.  PUSH AX   ;STORE NUMBER OF BLOCKS
  387.  MOV AX,WORD PTR BUFSG
  388.  MOV BX,WORD PTR BUFPS
  389.  PUSH AX
  390.  PUSH BX
  391.  PUSH AX
  392.  PUSH BX
  393.  MOV AX,WORD PTR KEY
  394.  PUSH CS
  395.  PUSH AX
  396.  MOV AX,OFFSET IV
  397.  PUSH CS
  398.  PUSH AX
  399.  PUSH AX ;MAKE IT LOOK LIKE A FAR CALL FOR IDEACFB
  400.  CMP BYTE PTR ENCRYPT,1
  401.  JNE DECRYPT
  402.  CALL _IDEACFB
  403.  JMP DONE_CRYPTSEC
  404. DECRYPT:
  405.  CALL _IDEACFBX
  406. DONE_CRYPTSEC:
  407. ; ADD SP,18
  408.  ADD SP,20 ;REMOVE EXTRA WORD
  409.  RET
  410.  
  411. NEXTSEC: ;INCREMENT HEAD, SECTOR, CYLINDER AS NEEDED TO GO TO NEXT SECTOR
  412.  MOV AX,[BP].SECSIZE
  413.  ADD WORD PTR BUFPS,AX ;GO TO NEXT BLOCK IN MEMORY
  414.  DEC BYTE PTR SECLFT   ;COUNT DOWN SECTORS LEFT
  415.  INC BYTE PTR CURSEC   ;INCREMENT SECTOR
  416.  MOV AL,BYTE PTR CURSEC
  417.  CMP AL,[BP].MAXSEC
  418.  JBE DONE_COUNT
  419.  MOV BYTE PTR CURSEC,1 ;RESET SECTOR
  420.  INC BYTE PTR CURHD    ;INCREMENT HEAD
  421.  MOV AL,BYTE PTR CURHD
  422.  CMP AL,[BP].MAXHD
  423.  JB DONE_COUNT
  424.  MOV BYTE PTR CURHD,0  ;RESET HEAD
  425.  INC WORD PTR CURCYL   ;THEN INCREMENT CYLINDER
  426. DONE_COUNT: RET
  427.  
  428. LOADBS:
  429.  CMP BYTE PTR DRIVE,1
  430.  JA IGBS             ;DON'T ALTER PARAMS FOR HARD DRIVE
  431.  MOV [BP].ACTIVE,0         ;DEFAULT OFF
  432.  MOV [BP].FLAG2M,0         ;DEFAULT NOT 2M-FORMATTED 1.3d
  433.  MOV ES,WORD PTR BUFSG
  434.  MOV SI,WORD PTR BUFPS         ;GET ACCESS TO BUFFER
  435.  CMP WORD PTR ES:[SI+510],0AA55h ;CHECK FOR BOOT-RECORD SIGNATURE
  436.  JNE IGBS             ;BAILOUT IF BOOT SECTOR LOOKS BAD
  437.  PUSH SI             ;Check both offsets for CRYP 1.3C
  438.  ADD  SI,WORD PTR INCFOF
  439.  CALL CKCRPF
  440.  POP  SI
  441.  JE   DKCRYPT
  442.  PUSH SI
  443.  ADD  SI,WORD PTR OUTCFOF
  444.  CALL CKCRPF
  445.  POP  SI
  446.  JE   DKCRYPT
  447.  JMP  NOTCRYPT
  448. IGBS: JMP IGNOREBS
  449. DKCRYPT:
  450.  PUSH SI            ;CHECK BOTH CKWD OFFSETS 1.3B
  451.  ADD  SI,WORD PTR INCFOF
  452.  CALL CKKEY
  453.  POP  SI
  454.  JE   GOODKEY
  455.  PUSH SI
  456.  ADD  SI,WORD PTR OUTCFOF
  457.  CALL CKKEY
  458.  POP  SI
  459.  JE   GOODKEY
  460.  JMP  NOTGOODKEY
  461.  
  462.  
  463. NOTGOODKEY:
  464.  MOV BYTE PTR BADKEY,1
  465.  JMP NOTCRYPT
  466. GOODKEY:
  467.  MOV [BP].ACTIVE,1 ;TURN ON ENCRYPTION
  468.  PUSH SI
  469.  MOV  DI,SI
  470.  ADD  DI,3       ;ES:DI -> SYSTEM ID IN BOOT SECT
  471.  MOV  SI,OFFSET ID2M
  472.  MOV  CX,6
  473.  CLD
  474.  REPE CMPSB
  475.  POP  SI
  476.  JNE  NOTCRYPT
  477.  MOV [BP].FLAG2M,1         ;2M-FORMATTED 1.3d
  478.  MOV AX,ES:[SI+22]         ;SECTORS FOR EACH FAT 1.3d
  479.  MOV [BP].FATSIZ,AX
  480. NOTCRYPT:
  481.  MOV AL,ES:[SI+18h]
  482.  MOV [BP].MAXSEC,AL ;STORE MAX SECTOR
  483.  MOV AL,ES:[SI+1Ah]
  484.  MOV [BP].MAXHD,AL  ;STORE MAX HEAD
  485.  MOV AX,ES:[SI+0Bh]
  486.  MOV [BP].SECSIZE,AX ;STORE BYTES PER SECTOR
  487.  MOV AX,ES:[SI+27h]
  488.  MOV [BP].SERIAL,AX  ;STORE FIRST WORD OF SERIAL NUMBER
  489.  MOV AX,ES:[SI+29h]
  490.  MOV [BP].SERIAL+2,AX ;STORE SECOND WORD OF SERIAL NUMBER
  491. IGNOREBS:
  492.  RET
  493.  
  494. CKCRPF PROC NEAR
  495.  CMP WORD PTR ES:[SI],'RC'
  496.  JNE CKCRPFR
  497.  CMP WORD PTR ES:[SI+2],'PY'
  498. CKCRPFR:
  499.  RET
  500. CKCRPF ENDP
  501.  
  502. CKKEY PROC NEAR
  503.  MOV AX,WORD PTR FKEYCHK
  504.  CMP WORD PTR ES:[SI+4],AX
  505.  JNE CKKEYRET
  506.  MOV AX,WORD PTR FKEYCHK+2
  507.  CMP WORD PTR ES:[SI+6],AX
  508. CKKEYRET:
  509.  RET
  510. CKKEY ENDP
  511.  
  512. ;VARIABLES HERE WILL BE LOADED BY LOGIN
  513.     ALIGN 4
  514. LOADDATA:
  515. TSRVER    DB '130D'            ;VERSION FOR CHECK
  516. REALBIOS LABEL DWORD
  517.     DW 0,0
  518. FKEYCHK:DW 2 DUP (0ffffh)
  519. FKEY:    DB 13,10,'Secure Drive Version 1.3d',13,10
  520.     DB 'TSR Installed',13,10,'$'
  521. ALRINS: DB 13,10,'Secure Drive TSR already resident',13,10,'$'
  522.     DB (104-($-FKEY)) DUP (0aah)      ;FLOPPY ENCRYPTION KEY
  523. FKEYV10 DB 0
  524.     DB "PPP"              ;PAD FOR ALIGNMENT
  525. HKEYCHK:DW 2 DUP (0ffffh)
  526. HKEY    LABEL BYTE
  527.     DB 104 DUP (0bbh)          ;HARD DRIVE ENCRYPTION KEY
  528. HKEYV10 DB 0
  529.     DB "PPP"              ;PAD FOR ALIGNMENT
  530. INCFOF    DW 3                  ;INPUT CHECKWORD OFFSET IN BOOT REC  1.3B
  531. OUTCFOF DW 502                  ;OUTPUT CHECKWORD OFFSET IN BOOT REC 1.3B
  532. FDA:    DISKDATA <0,'A',0,0,1,0FFFFh,18,2,512,0,0,0,0,0>
  533. FDB:    DISKDATA <0,'B',0,0,1,0FFFFh,18,2,512,0,0,0,0,0>
  534. HD1:    DISKDATA <0,'Z',0FFFFh,0,0,0,0,0,512,0,0,0,0,0>
  535. HD2    LABEL BYTE
  536.     REPT MAXDRV-1
  537.     DISKDATA <0,'Z',0FFFFh,0,0,0,0,0,512,0,0,0,0,0>
  538.     ENDM
  539.  
  540.     ALIGN 4
  541. ;VARIABLES HERE STAY PUT
  542. STKSEG: DW ? ;SEGMENT OF USER STACK
  543. STKOFS: DW ? ;OFFSET OF USER STACK
  544.  
  545. RQTYPE: DB ? ;REQUEST TYPE, AH FROM CALL
  546. DRIVE:    DB ? ;DRIVE FROM CALL
  547. NUMSEC: DB ? ;NUMBER OF SECTORS TO READ (AL FROM CALL)
  548. SECLFT: DB ? ;NUMBER OF SECTORS LEFT TO PROCESS
  549. CALLCX: DW ? ;ORIGINAL CX
  550. KEY:    DW ? ;CURRENTLY SELECTED KEY
  551. BADKEY: DB ? ;KEY BAD FLAG
  552.  
  553. STCYL:    DW ? ;START CYLINDER FROM CALL
  554. CURCYL: DW ? ;CURRENT CYLINDER BEING PROCESSED
  555.  
  556. STSEC:    DB ? ;START SECTOR FROM CALL
  557. CURSEC: DB ? ;CURRENT SECTOR BEING PROCESSED
  558.  
  559. STHD:    DB ? ;START HEAD FROM CALL
  560. CURHD:    DB ? ;CURRENT HEAD BEING PROCESSED
  561.  
  562. BUFOS:    DW ? ;OFFSET OF TARGET BUFFER
  563. BUFPS:    DW ? ;CURRENT POSITION WITHIN BUFFER
  564. BUFSG:    DW ? ;SEGMENT OF TARGET BUFFER
  565.  
  566. ENCRYPT: DB ? ;1 FOR ENCRYPT, 0 FOR DECRYPT
  567. IV:  DB 8 DUP (?)   ;IV FOR CFB
  568. ID2M     DB    "2M-STV"     ; ID FOR 2M-FORMATTED DISKETTE
  569.  
  570. ; Copyright (c) 1993 Colin Plumb.  This code may be freely
  571. ; distributed under the terms of the GNU General Public Licence.
  572.  
  573. ; A core operation in IDEA is multiplication modulo 65537.
  574. ; The valid inputs, 1 through 66636 inclusive are represented in
  575. ; 16-bit registers modulo 65536.  I.e. a value of 0 means 65536,
  576. ; or -1.  Thus, we need to test for that specially.  -x, modulo
  577. ; 65537, is 65537-x = 1-x.
  578. ; For any other number, represent the product as a*65536+b.  Since
  579. ; 65536 = -1 (mod 65537), this is the same number as b-a.  Should
  580. ; this result be negautive (generate a borrow), -n mod 65537 = 1-n
  581. ; mod 65536.  Or in other words, if you add the borrow bit back on,
  582. ; you get the right answer.
  583.  
  584. ; This is what the assembly code does.    It forms a zero, and adds
  585. ; that on with carry.
  586.  
  587. ; Another useful optimisation takes advantage of the fact that
  588. ; a and b are equal only if the answer is congruent to 0 mod 65537.
  589. ; Since 65537 is prime, this happens only if one of the inputs is
  590. ; congruent to 0 mod 65537.  Since the inputs are all less than 65537,
  591. ; this means it must have been zero.
  592.  
  593. ; The code below tests for a zero result of the subtraction, and if
  594. ; one arises, it branches out of line to figure out what happened.
  595.  
  596.  
  597. ; This code implemets the IDEA encryption algorithm.
  598. ; It follows in pseudo-C, where the * operator operates
  599. ; modulo 65537, as Idea needs.    (If you don't understand,
  600. ; learn IDEA better.)
  601.  
  602. ; IDEA is works on 16-bit units.  If you're processing bytes,
  603. ; it's defined to be big-endian, so an Intel machine needs to
  604. ; swap the bytes around.
  605.  
  606. ; void Idea(u_int16 *in, u_int16 *out, u_int16 *key)
  607. ; {
  608. ;     register u+int16 x0, x1, x2, x3, s1, s2, round;
  609. ;
  610. ;     x0 = *in++;  x1 = *in++;  x2 = *in++;    x3 = *in;
  611. ;
  612. ;     for (round = 0; round < 8; round++) {
  613. ;         x0 *= *key++;
  614. ;         x1 += *key++;
  615. ;         x2 += *key++;
  616. ;         x3 *= *key++;
  617. ;
  618. ;         s1  = x1;  s2    = x2;
  619. ;         x2 ^= x0;  x1 ^= x3;
  620. ;
  621. ;         x2 *= *key++;
  622. ;         x1 += x2;
  623. ;         x1 *= *key++;
  624. ;         x2 += x1;
  625. ;
  626. ;         x0 ^= x1;  x3 ^= x2;
  627. ;         x1 ^= s2;  x2 ^= s1;
  628. ;     }
  629. ;     *out++ = x0 * *key++;
  630. ;     *out++ = x2 + *key++;          /* Yes, this is x2, not x1 */
  631. ;     *out++ = x1 + *key++;
  632. ;     *out    = x3 * *key;
  633. ; }
  634.  
  635. ; ds:si points to key, ax, dx are temps, args in bx, cx, di, bp
  636. ; Trashes *all* registers.  direction flag must be clear.
  637. ; Leaves es zero.
  638.  
  639. ; Since there is no spare register to hold the loop count, I make
  640. ; clever use of the stack, pushing the start of the loop several
  641. ; times and using a ret instruction to do the return.
  642.  
  643. ; Annoyingly, lods is fastest on 8086's, but other techniques are
  644. ; best on 386's.  Well, that's what the manual says, but real
  645. ; life is different.  USELODS wins on a 386SX, at least.
  646. ; Leave it set for all platforms.
  647.  
  648. USELODS        equ      1
  649.  
  650. ; bp must be x0 for some of the code below to work
  651. x0      equ         bp
  652. x1      equ         bx
  653. x2      equ         cx
  654. x3      equ         di
  655. ; di must be x3 for some of the code below to work
  656.  
  657. ;; Now, this is rather interesting.  We test for zero arguments
  658. ;; after the multiply.    Assuming random inputs, one or both are
  659. ;; zero (2^17-1)/2^32, or approximately 1/32786 of the time.
  660. ;; Encryption in any feedback mode produces essentially random
  661. ;; inputs, so average-case analysis is okay.  While we don't
  662. ;; want the out-of-line code to waste time, it is not worth
  663. ;; slowing down the in-line case to speed it up.
  664. ;;
  665. ;; Basically, we start inverting the source x, and if that was 0,
  666. ;; we use the inverse of the key instead.
  667.  
  668. Core1Z:
  669.     neg       x0
  670.     jnz       Core1Za
  671. if USELODS
  672.     sub       x0,[si-2]
  673. else
  674.     sub       x0,[si]
  675. endif
  676. Core1Za:
  677.     inc       x0
  678.     jmp       Core1done
  679. Core2Z:
  680.     neg       x3
  681.     jnz       Core2Za
  682. if USELODS
  683.     sub       x3,[si-2]
  684. else
  685.     sub       x3,[si+6]
  686. endif
  687. Core2Za:
  688.     inc       x3
  689.     jmp       Core2done
  690. Core3Z:
  691.     neg       x2
  692.     jnz       Core3Za
  693. if USELODS
  694.     sub       x2,[si-2]
  695. else
  696.     sub       x2,[si+8]
  697. endif
  698. Core3Za:
  699.     inc       x2
  700.     jmp       Core3done
  701. Core4Z:
  702.     neg       x1
  703.     jnz       Core4Za
  704. if USELODS
  705.     sub       x1,[si-2]
  706. else
  707.     sub       x1,[si+10]
  708. endif
  709. Core4Za:
  710.     inc       x1
  711.     jmp       Core4done
  712.  
  713. ; We need a constant 0 that we can move into a register without affecting
  714. ; the carry flag (as the classic xor ax,ax is wont to do), so we use the
  715. ; es register for a constant 0 source.    This is okay even in protected
  716. ; mode.  (I *told* you this was tricky code!)
  717.  
  718. ; BTW, since you wanted to know, this is 8 + 78*4 + 16 = 336 instructions.
  719.  
  720. Core        proc    near
  721.     xor       ax,ax
  722.     mov       es,ax
  723.     mov       ax,OFFSET Finish
  724.     push        ax
  725.     mov       ax,OFFSET Coreloop
  726.     push        ax          ; Loop 3 times, then return
  727.     push        ax
  728.     push        ax
  729.  
  730. Coreloop:
  731. if USELODS
  732.     lodsw
  733. else
  734.     mov       ax,[si]          ; x0 *= *key++
  735. endif
  736.     mul       x0
  737.     sub       ax,dx
  738.     jz      Core1Z
  739.     mov       x0,es
  740.     adc       x0,ax
  741. Core1done:
  742.  
  743. if USELODS
  744.     lodsw
  745.     add       x1,ax
  746.     lodsw
  747.     add       x2,ax
  748. else
  749.     add       x1,[si+2]        ; x1 += *key++
  750.     add       x2,[si+4]        ; x2 += *key++
  751. endif
  752.  
  753. if USELODS
  754.     lodsw
  755. else
  756.     mov       ax,[si+6]        ; x3 += *key++
  757. endif
  758.     mul       x3
  759.     sub       ax,dx
  760.     jz      Core2Z
  761.     mov       x3,es
  762.     adc       x3,ax
  763. Core2done:
  764.  
  765.     push        x1            ; s1 = x1
  766.     push        x2              ; s2 = x2
  767.  
  768.     xor       x1,x3        ; x1 ^= x3
  769.     xor       x2,x0        ; x2 ^= x0
  770.  
  771. if USELODS
  772.     lodsw
  773. else
  774.     mov       ax,[si+8]        ; x2 *= *key++
  775. endif
  776.     mul       x2
  777.     sub       ax,dx
  778.     jz      Core3Z
  779.     mov       x2,es
  780.     adc       x2,ax
  781. Core3done:
  782.  
  783.     add       x1,x2        ; x1 += x2
  784.  
  785. if USELODS
  786.     lodsw
  787. else
  788.     mov       ax,[si+10]         ; x1 *= *key++
  789. endif
  790.     mul       x1
  791.     sub       ax,dx
  792.     jz      Core4Z
  793.     mov       x1,es
  794.     adc       x1,ax
  795. Core4done:
  796.  
  797.     add       x2,x1        ; x2 += x1
  798.  
  799.     xor       x0,x1        ; x0 ^= x1
  800.     xor       x3,x2        ; x3 ^= x2
  801.  
  802.     pop       dx
  803.     xor       x1,dx        ; x1 ^= s2
  804.     pop       dx
  805.     xor       x2,dx        ; x2 ^= s1
  806.  
  807. ; Second unrolling of loop
  808. if USELODS
  809.     lodsw
  810. else
  811.     mov    ax,[si+12]        ; x0 *= *key++
  812. endif
  813.     mul       x0
  814.     sub       ax,dx
  815.     jz      Core5Z
  816.     mov       x0,es
  817.     adc       x0,ax
  818. Core5done:
  819.  
  820. if USELODS
  821.     lodsw
  822.     add       x1,ax
  823.     lodsw
  824.     add       x2,ax
  825. else
  826.     add       x1,[si+14]         ; x1 += *key++
  827.     add       x2,[si+16]         ; x2 += *key++
  828. endif
  829.  
  830. if USELODS
  831.     lodsw
  832. else
  833.     mov       ax,[si+18]         ; x3 *= *key++
  834. endif
  835.     mul       x3
  836.     sub       ax,dx
  837.     jz      Core6Z
  838.     mov       x3,es
  839.     adc       x3,ax
  840. Core6done:
  841.  
  842.     push        x1             ; s1 = x1
  843.     push        x2              ; s2 = x2
  844.  
  845.     xor       x1,x3        ; x1 ^= x3
  846.     xor       x2,x0        ; x2 ^= x0
  847.  
  848. if USELODS
  849.     lodsw
  850. else
  851.     mov       ax,[si+20]         ; x2 *= *key++
  852. endif
  853.     mul       x2
  854.     sub       ax,dx
  855.     jz      Core7Z
  856.     mov       x2,es
  857.     adc       x2,ax
  858. Core7done:
  859.  
  860.     add       x1,x2        ; x1 += x2
  861.  
  862. if USELODS
  863.     lodsw
  864. else
  865.     mov       ax,[si+22]         ; x1 *= *key++
  866. endif
  867.     mul       x1
  868.     sub       ax,dx
  869.     jz      Core8Z
  870.     mov       x1,es
  871.     adc       x1,ax
  872. Core8done:
  873.  
  874.     add       x2,x1        ; x2 += x1
  875.  
  876.     xor       x0,x1        ; x0 ^= x1
  877.     xor       x3,x2        ; x3 ^= x2
  878.  
  879.     pop       dx
  880.     xor       x1,dx        ; x1 ^= s2
  881.     pop       dx
  882.     xor       x2,dx        ; x2 ^= s1
  883.  
  884. ife USELODS
  885.     lea       si,[si+24]
  886. endif
  887.  
  888.     ret       ; Used as a loop instruction!
  889.  
  890. Core5Z:
  891.     neg       x0
  892.     jnz       Core5Za
  893. if USELODS
  894.     sub       x0,[si-2]
  895. else
  896.     sub       x0,[si+12]
  897. endif
  898. Core5Za:
  899.     inc       x0
  900.     jmp       Core5done
  901. Core6Z:
  902.     neg       x3
  903.     jnz       Core6Za
  904. if USELODS
  905.     sub       x3,[si-2]
  906. else
  907.     sub       x3,[si+18]
  908. endif
  909. Core6Za:
  910.     inc       x3
  911.     jmp       Core6done
  912. Core7Z:
  913.     neg       x2
  914.     jnz       Core7Za
  915. if USELODS
  916.     sub       x2,[si-2]
  917. else
  918.     sub       x2,[si+20]
  919. endif
  920. Core7Za:
  921.     inc       x2
  922.     jmp       Core7done
  923. Core8Z:
  924.     neg       x1
  925.     jnz       Core8Za
  926. if USELODS
  927.     sub       x1,[si-2]
  928. else
  929.     sub       x1,[si+22]
  930. endif
  931. Core8Za:
  932.     inc       x1
  933.     jmp       Core8done
  934. Core9Z:
  935.     neg       x0
  936.     jnz       Core9Za
  937. if USELODS
  938.     sub       x0,[si-2]
  939. else
  940.     sub       x0,[si]
  941. endif
  942. Core9Za:
  943.     inc       x0
  944.     jmp       Core9done
  945. ; Special: compute into dx (zero on entry)
  946. Core10Z:
  947.     sub       dx,x3
  948.     jnz       Core10Za
  949. if USELODS
  950.     sub       dx,[si-2]
  951. else
  952.     sub       dx,[si+6]
  953. endif
  954. Core10Za:
  955.     inc       dx
  956. ;     jmp        Core10done
  957.     ret
  958.  
  959.  
  960. Finish:
  961. if USELODS
  962.     lodsw
  963. else
  964.     mov       ax,[si]          ; x0 *= *key++
  965. endif
  966.     mul       x0
  967.     sub       ax,dx
  968.     jz      Core9Z
  969.     mov       x0,es
  970.     adc       x0,ax
  971. Core9done:
  972.  
  973.     xchg        x1,x2
  974. if USELODS
  975.     lodsw
  976.     add       x1,ax
  977.     lodsw
  978.     add       x2,ax
  979. else
  980.     add       x1,[si+2]        ; x1 += *key++
  981.     add       x2,[si+4]       ; x2 += *key++
  982. endif
  983.  
  984. ; This is special: compute into dx, not x3
  985. if USELODS
  986.     lodsw
  987. else
  988.     mov       ax,[si+6]        ; x3 *= *key++
  989. endif
  990.     mul       x3
  991.     sub       ax,dx
  992.     mov       dx,es
  993.     jz      Core10Z
  994.     adc       dx,ax
  995. Core10done:
  996.  
  997.     ret
  998.  
  999.     endp
  1000.  
  1001. ; Okay, the basic plan for the CFB kernel is
  1002. ; get x0,x1,x2,x3
  1003. ; get key pointer
  1004. ; call core
  1005. ; get buffer pointers
  1006. ;Loop:
  1007. ; lodsw
  1008. ; xor         ax,x0
  1009. ; mov    x0,ax
  1010. ; stosw
  1011. ; lodsw
  1012. ; xor         ax,x1
  1013. ; mov         x0,ax
  1014. ; stosw
  1015. ; lodsw
  1016. ; xor         ax,x2
  1017. ; mov         x0,ax
  1018. ; stosw
  1019. ; lodsw
  1020. ; xor         ax,x3
  1021. ; mov         x3,ax
  1022. ; stosw
  1023. ; push buffer pointers
  1024. ; get key pointer
  1025. ; call          core
  1026. ; pop buffer pointers
  1027. ; loop
  1028. ; lodsw/xor/etc.
  1029. ;
  1030. ;
  1031. ; This function is designed to go in the middle of a byte-granularity
  1032. ; CFB engine.  It performs "len" encryptions of the IV, encrypting
  1033. ; 8*(len-1) bytes from the source to the destination.  The idea is
  1034. ; that you first xor any odd leading bytes, then call this function,
  1035. ; then xor up to 8 trailing bytes.
  1036.  
  1037. ; The main loop in this is 38 instructions, plus the 336 for the core
  1038. ; makes 374 total.  That's 46.75 instructions per byte.
  1039. ; (It's the same for IdeaCFBx)
  1040.  
  1041. ; IV, key, plain, cipher, len
  1042. ;     public        _IdeaCFB
  1043. ;_IdeaCFB proc far     ; Args are at [sp+4]
  1044. _IDEACFB:
  1045.     cld
  1046.     push        bp
  1047.     push        si
  1048.     push        di
  1049.     push        ds          ; 8 more words here, so args are at [sp+12]
  1050. ; To be precise, IV is at 12, key at 16, plain at 20,
  1051. ; cipher at 24 and len at 28
  1052.     mov       bp,sp
  1053.     lds       si,[bp+12]         ; IV
  1054. ; Load and byte-swap IV
  1055.     mov       ax,[si]
  1056.     xchg        ah,al
  1057.     mov       x1,[si+2]
  1058.     mov       x2,[si+4]
  1059.     xchg        bh,bl
  1060.     xchg        ch,cl
  1061.     mov       dx,[si+6]
  1062.     xchg        dh,dl
  1063.  
  1064.     lds       si,[bp+16]         ; Key
  1065.     mov       x0,ax
  1066.     mov       x3,dx
  1067.  
  1068.     call        Core
  1069. IdeaCFBLoop:
  1070. ;     mov        ax,x0
  1071. ;     mov        bp,sp
  1072. ;     dec        WORD PTR [bp+28]        ; Decrement count
  1073. ;     jz       IdeaCFBEnd
  1074. ;     lds        si,[bp+20]
  1075. ;     les        di,[bp+24]
  1076. ;     mov        x0,ax
  1077. ; Alternate code: (which is faster?  Two moves or three segment overrides?)
  1078.     mov       si,sp
  1079.     dec       WORD PTR ss:[si+28]
  1080.     jz      IdeaCFBEnd
  1081.     les       di,ss:[si+24]
  1082.     lds       si,ss:[si+20]
  1083.  
  1084.     lodsw
  1085.     xchg        ah,al
  1086.     xor       ax,x0
  1087.     mov       x0,ax
  1088.     xchg        ah,al
  1089.     stosw
  1090.     lodsw
  1091.     xchg        ah,al
  1092.     xor       ax,x1
  1093.     mov       x1,ax
  1094.     xchg        ah,al
  1095.     stosw
  1096.     lodsw
  1097.     xchg        ah,al
  1098.     xor       ax,x2
  1099.     mov       x2,ax
  1100.     xchg        ah,al
  1101.     stosw
  1102.     lodsw
  1103.     xchg        ah,al
  1104.     xor       ax,dx
  1105.     mov       dx,ax
  1106.     xchg        ah,al
  1107.     stosw
  1108.  
  1109. ;     mov        ax,x0
  1110. ;     mov        bp,sp
  1111. ;     mov        [bp+20],si          ; Save source offset
  1112. ;     mov        [bp+24],di          ; Save destination offset
  1113. ;     lds        si,[bp+16]          ; Key
  1114. ;     mov        x0,ax         ; Get x0 in place for another iteration
  1115. ; Alternate code for the above: (which is faster?  One move or three ss:?)
  1116.     mov       ax,si
  1117.     mov       si,sp
  1118.     mov       ss:[si+20],ax
  1119.     mov       ss:[si+24],di
  1120.     lds       si,ss:[si+16]
  1121.  
  1122.     mov       x3,dx        ; Get x3 in place
  1123.     mov       ax,OFFSET IdeaCFBLoop
  1124.     push        ax
  1125.     jmp       Core
  1126.  
  1127. IdeaCFBEnd:
  1128. ;     lds        si,[bp+12]
  1129.     lds       di,ss:[si+12]    ; Get IV for writing back
  1130.  
  1131.     mov       ax,x0
  1132.     xchg        ah,al
  1133.     mov       [di],ax          ; Use stosw?
  1134.     xchg        bh,bl
  1135.     xchg        ch,cl
  1136.     mov       [di+2],x1
  1137.     mov       [di+4],x2
  1138.     xchg        dh,dl
  1139.     mov       [di+6],dx
  1140.  
  1141.     pop       ds
  1142.     pop       di
  1143.     pop       si
  1144.     pop       bp
  1145.  
  1146.     ret
  1147.  
  1148.     endp
  1149.  
  1150. ; This decoding step is similar, except that instead of
  1151. ;     lods
  1152. ;     xor        x0,ax
  1153. ;     mov        ax,x0
  1154. ;      stos
  1155. ; the feedback step is
  1156. ;     lods
  1157. ;     xchg         x0,ax
  1158. ;     xor        ax,x0
  1159. ;     stos
  1160.  
  1161. ; IV, key, cipher, plain, len
  1162. ;     public        _IdeaCFBx
  1163. ;_IdeaCFBx proc far      ; Args are at [sp+4]
  1164. _IDEACFBX:
  1165.     cld
  1166.     push        bp
  1167.     push        si
  1168.     push        di
  1169.     push        ds          ; 8 more words here, so args are at [sp+12]
  1170.     mov       bp,sp
  1171.     lds       si,[bp+12]         ; IV
  1172. ; Load and byte-swap IV
  1173.     mov       ax,[si]
  1174.     xchg        ah,al
  1175.     mov       x1,[si+2]
  1176.     mov       x2,[si+4]
  1177.     xchg        bh,bl
  1178.     xchg        ch,cl
  1179.     mov       dx,[si+6]
  1180.     xchg        dh,dl
  1181.  
  1182.     lds       si,[bp+16]         ; Key
  1183.     mov       x0,ax
  1184.     mov       x3,dx
  1185.  
  1186.     call        Core
  1187. IdeaCFBxLoop:
  1188. ;     mov        ax,x0
  1189. ;     mov        bp,sp
  1190. ;     dec        WORD PTR [bp+28]        ; Decrement count
  1191. ;     jz       IdeaCFBxEnd
  1192. ;     lds        si,[bp+20]
  1193. ;     les        di,[bp+24]
  1194. ;     mov        x0,ax
  1195. ; Alternate code: (which is faster?  Two moves or three segment overrides)
  1196.     mov       si,sp
  1197.     dec       WORD PTR ss:[si+28]
  1198.     jz      IdeaCFBxEnd
  1199.     les       di,ss:[si+24]
  1200.     lds       si,ss:[si+20]
  1201.  
  1202.     lodsw
  1203.     xchg        ah,al
  1204.     xchg        x0,ax
  1205.     xor       ax,x0
  1206.     xchg        ah,al
  1207.     stosw
  1208.     lodsw
  1209.     xchg        ah,al
  1210.     xchg        x1,ax
  1211.     xor       ax,x1
  1212.     xchg        ah,al
  1213.     stosw
  1214.     lodsw
  1215.     xchg        ah,al
  1216.     xchg        x2,ax
  1217.     xor       ax,x2
  1218.     xchg        ah,al
  1219.     stosw
  1220.     lodsw
  1221.     xchg        ah,al
  1222.     xchg        dx,ax
  1223.     xor       ax,dx
  1224.     xchg        ah,al
  1225.     stosw
  1226.  
  1227. ;     mov        ax,x0
  1228. ;     mov        bp,sp
  1229. ;     mov        [bp+20],si          ; Save source offset
  1230. ;     mov        [bp+24],di          ; Save destination offset
  1231. ;     lds        si,[bp+16]          ; Key
  1232. ;     mov        x0,ax         ; Get x0 in place for another iteration
  1233. ; Alternate code for the above: (which is faster?  One move or three ss:?)
  1234.     mov       ax,si
  1235.     mov       si,sp
  1236.     mov       ss:[si+20],ax
  1237.     mov       ss:[si+24],di
  1238.     lds       si,ss:[si+16]
  1239.  
  1240.     mov       x3,dx        ; Get x3 in place
  1241.     mov       ax,OFFSET IdeaCFBxLoop
  1242.     push        ax
  1243.     jmp       Core
  1244.  
  1245. IdeaCFBxEnd:
  1246. ;     lds        si:[bp+12]
  1247.     lds       di,ss:[si+12]    ; Get IV for writing back
  1248.  
  1249.     mov       ax,x0
  1250.     xchg        ah,al
  1251.     mov       [di],ax          ; Use stosw?
  1252.     xchg        bh,bl
  1253.     xchg        ch,cl
  1254.     mov       [di+2],x1
  1255.     mov       [di+4],x2
  1256.     xchg        dh,dl
  1257.     mov       [di+6],dx
  1258.  
  1259.  
  1260.     pop       ds
  1261.     pop       di
  1262.     pop       si
  1263.     pop       bp
  1264.  
  1265.     ret
  1266.  
  1267.     endp
  1268. END_OF_FILE:
  1269. _TEXT ENDS
  1270. END START
  1271.